//
// Created by pulsarv on 19-7-24.
//

#ifndef EASYMVM_NESEMULATOR_H
#define EASYMVM_NESEMULATOR_H

#include <modules/VMCore/include/base_vm_env/base_vm_env.hpp>
#include <cmath>

#define NES_SCREEN_ROWS 32
#define NES_SCREEN_COLS 64

#define NES_MEM_SIZE 4096
#define NES_GFX_ROWS 32
#define NES_GFX_COLS 64
#define NES_GFX_SIZE (NES_GFX_ROWS * NES_GFX_COLS)
#define NES_STACK_SIZE 16
#define NES_KEY_SIZE 16

#define NES_CLOCK_HZ 60
#define NES_CLOCK_RATE_MS ((int) ((1.0 / NES_CLOCK_HZ) * 1000 + 0.5))

class NESEmulator : public base_vm_env {
public:
    char screen[NES_SCREEN_ROWS][NES_SCREEN_COLS][3];
    unsigned short opcode;
    uint8_t memory[NES_MEM_SIZE];

    uint8_t V[16];

    uint16_t I;
    uint16_t PC;
    uint8_t gfx[NES_GFX_ROWS][NES_GFX_COLS];
    //TODO:计数器
    uint8_t delay_timer;
    uint8_t sound_timer;

    //TODO:堆栈
    uint16_t stack[NES_STACK_SIZE];
    uint16_t SP;

    //TODO:按键
    uint8_t key[NES_KEY_SIZE];


    int screen_rows = NES_SCREEN_ROWS;
    int screen_cols = NES_SCREEN_COLS;
    int clock_rate_ms = NES_CLOCK_RATE_MS;
    int clock_hz = NES_CLOCK_HZ;

    const char *name = "NES";

    bool draw_flag;

    void runCycle() override;

    void loadGame(char *file_path);

    void debug_screen();

    unsigned short get_opcode();

    void setkeys(int index, int state);

    void tick() override;

    void draw_screen(uint8_t x, uint8_t y, uint8_t n);

    void printState() override;

    void initialize() override;

    void print_cpu_info() override;

};


#endif //EASYMVM_NESEMULATOR_H
